package com.wbs.batis.rest;

import com.wbs.batis.rest.annotation.EnableRestMapper;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class RestInterfaceRegister {

    Logger log = LoggerFactory.getLogger(RestInterfaceRegister.class);

    RequestMappingHandlerMapping requestMappingHandlerMapping;
    SqlSessionTemplate sqlSessionTemplate;

    public RestInterfaceRegister(RequestMappingHandlerMapping requestMappingHandlerMapping, SqlSessionTemplate sqlSessionTemplate) {
        this.requestMappingHandlerMapping = requestMappingHandlerMapping;
        this.sqlSessionTemplate = sqlSessionTemplate;
    }



    /**
     * register batis mapper interface as rest interface
     * attention: call after batis initialed.
     * @param mapperInterface
     * @return
     */

    public Object register(Class<?> mapperInterface){

        EnableRestMapper enableRestMapper = mapperInterface.getAnnotation(EnableRestMapper.class);

        RestMapperProxy restMapperProxy = new RestMapperProxy(mapperInterface, sqlSessionTemplate);
        //注册代理
        Object proxy = Proxy.newProxyInstance(RestInterfaceRegister.class.getClassLoader(), new Class[]{mapperInterface}, restMapperProxy);

        //注册接口
        for(Method method : mapperInterface.getMethods()){

            String uri = enableRestMapper.value() + "/" + method.getName();
            log.info("mapper rest [{} - {}]", uri, method.getDeclaringClass());

            RequestMappingInfo mappingInfo = new RequestMappingInfo(
                    new PatternsRequestCondition(uri),
                    new RequestMethodsRequestCondition(commandTypeToRequestMethod(method)),
                    null, null, null, null, null);

            requestMappingHandlerMapping.registerMapping(mappingInfo, proxy, method);

        }

        return proxy;

    }

    private RequestMethod commandTypeToRequestMethod(Method method){
        MappedStatement statement = sqlSessionTemplate.getConfiguration().getMappedStatement(method.getName());
        SqlCommandType commandType = statement.getSqlCommandType();

        if(SqlCommandType.SELECT == commandType){
            return RequestMethod.GET;
        }
        return RequestMethod.POST;
    }

}
